package org.frasermccrossan.toneitdown;

import java.util.ArrayList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

class ProfileDatabaseHelper {
	
	private ProfileOpenHelper openHelper;
	private SQLiteDatabase db;
	
	ProfileDatabaseHelper(Context c) {
		openHelper = new ProfileOpenHelper(c);
		db = openHelper.getWritableDatabase();
	}

	public void close() {
		db.close();
	}
	
	Cursor allProfiles() {
		return db.query(ProfileOpenHelper.PROFILE_TABLE_NAME,
	            new String[] { "_id", ProfileOpenHelper.NAME, ProfileOpenHelper.VOLUME, ProfileOpenHelper.VIBRATE },
				null,
				null, null, null, "_id");
	}
	
	boolean isCurrent(long profileId) {
		return getCurrentProfileId() == profileId;
	}
	
	// get a profile by ID
	Profile getProfileById(long profileId) {
		Cursor c = db.query(ProfileOpenHelper.PROFILE_TABLE_NAME,
				            new String[] { ProfileOpenHelper.NAME, ProfileOpenHelper.VOLUME, ProfileOpenHelper.VIBRATE },
							String.format("%s = %d", "_id", profileId),
							null, null, null, "1");
		if (c.moveToFirst()) {
			Profile rv = new Profile(profileId, c.getString(0), Integer.parseInt(c.getString(1)), Integer.parseInt(c.getString(2)));
			c.close();
			return rv;
		}
		else {
			return null;
		}
	}
	
	public long getPrimaryProfileId() {
		Cursor c = db.query(ProfileOpenHelper.STATUS_TABLE_NAME,
				            new String[] { ProfileOpenHelper.CURRENT_PROFILE },
							null, null, null, null, "1");
		if (c.moveToFirst()) {
			long rv = c.getLong(0);
			c.close();
			return rv;
		}
		else {
			return ProfileOpenHelper.NULL_PROFILE;
		}
		
	}
	
	public long getCurrentProfileId() {
		Cursor c = db.query(ProfileOpenHelper.STATUS_TABLE_NAME,
				            new String[] { ProfileOpenHelper.CURRENT_PROFILE, ProfileOpenHelper.TIMED_PROFILE },
							null, null, null, null, "1");
		if (c.moveToFirst()) {
			long current = c.getLong(0);
			long timed = c.getInt(1);
			c.close();
			return (timed == ProfileOpenHelper.NULL_PROFILE) ? current : timed;
		}
		else {
			return ProfileOpenHelper.NULL_PROFILE;
		}
		
	}
	
	public Profile getCurrentProfile() {
		long currentId = getCurrentProfileId();
		return getProfileById(currentId);
	}
	
	public String getCurrentProfileName() {
		Profile current = getCurrentProfile();
		if (current != null) {
			return current.name;
		}
		else {
			return null;
		}
	}
	
	public ProfileInfo getProfileInfo() {
		Cursor c = db.query(ProfileOpenHelper.STATUS_TABLE_NAME,
				new String[] { ProfileOpenHelper.CURRENT_PROFILE,
				ProfileOpenHelper.TIMED_PROFILE, 
				ProfileOpenHelper.TIMED_EXPIRY },
				null, null, null, null, "1");
		if (c.moveToFirst()) {
			ProfileInfo info = new ProfileInfo();
			info.currentProfile = c.getInt(0);
			info.timedProfile = c.getInt(1);
			info.timedExpiry = c.getLong(2);
			c.close();
			return info;
		}
		else {
			return null;
		}
	}

	ArrayList<HourMinute> getHistory() {
		Cursor c = db.query(ProfileOpenHelper.HISTORY_TABLE_NAME,
				new String[] { ProfileOpenHelper.HOUR_OF_DAY, ProfileOpenHelper.MINUTE },
				null, null, null, null,
				ProfileOpenHelper.HOUR_OF_DAY + "," + ProfileOpenHelper.MINUTE,
				null);
		ArrayList<HourMinute> a = new ArrayList<HourMinute>(c.getCount());
		for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
			HourMinute hm = new HourMinute(c.getInt(0), c.getInt(1));
			a.add(hm);
		}
		c.close();
		return a;
	}
	
	boolean setName(long id, CharSequence name) {
		ContentValues cv = new ContentValues(1);
		cv.put(ProfileOpenHelper.NAME, name.toString());
		return (db.update(ProfileOpenHelper.PROFILE_TABLE_NAME, cv,
				"_id = ?", new String[] { "" + id }) == 1);
	}

	boolean setVolume(long id, int volumePercentage) {
		ContentValues cv = new ContentValues(1);
		cv.put(ProfileOpenHelper.VOLUME, volumePercentage);
		return (db.update(ProfileOpenHelper.PROFILE_TABLE_NAME, cv,
				"_id = ?", new String[] { "" + id }) == 1);
	}

	boolean setVibrate(long id, boolean vibrate) {
		ContentValues cv = new ContentValues(1);
		cv.put(ProfileOpenHelper.VIBRATE, vibrate ? 1 : 0);
		return (db.update(ProfileOpenHelper.PROFILE_TABLE_NAME, cv,
				"_id = ?", new String[] { "" + id }) == 1);
	}
	
	boolean setProfile(long id) {
		ContentValues cv = new ContentValues(2);
		cv.put(ProfileOpenHelper.CURRENT_PROFILE, id);
		cv.put(ProfileOpenHelper.TIMED_PROFILE, ProfileOpenHelper.NULL_PROFILE);
		return (db.update(ProfileOpenHelper.STATUS_TABLE_NAME, cv,
				null, null) == 1);
	}
	
	boolean setTimedProfile(long id, long expiry) {
		if (getPrimaryProfileId() == ProfileOpenHelper.NULL_PROFILE) {
			/* if we don't have a primary yet, just set it rather than
			 * trying to set a secondary without a primary
			 */
			return setProfile(id);
		}
		ContentValues cv = new ContentValues(2);
		cv.put(ProfileOpenHelper.TIMED_PROFILE, id);
		cv.put(ProfileOpenHelper.TIMED_EXPIRY, expiry);
		return (db.update(ProfileOpenHelper.STATUS_TABLE_NAME, cv,
				null, null) == 1);
	}
	
	boolean clearTimedProfile() {
		return setTimedProfile(ProfileOpenHelper.NULL_PROFILE, 0);
	}
	
	// true if the given profile is either the current or the timed
	boolean profileIsActive(long profileId) {
		Cursor c = db.query(ProfileOpenHelper.STATUS_TABLE_NAME,
				            new String[] { ProfileOpenHelper.CURRENT_PROFILE, ProfileOpenHelper.TIMED_PROFILE },
							null, null, null, null, "1");
		if (c.moveToFirst()) {
			long rvCurrent = c.getLong(0);
			long rvTimed = c.getLong(1);
			c.close();
			return (profileId == rvCurrent) || (profileId == rvTimed);
		}
		return false;
	}
	
	boolean deleteProfile(long id) {
		return (db.delete(ProfileOpenHelper.PROFILE_TABLE_NAME, "_id = ?",
				new String[] { String.valueOf(id) }) == 1);
		
	}
	
	long createEmptyProfile() {
		ContentValues cv = new ContentValues(3);
		cv.put(ProfileOpenHelper.NAME, "");
		cv.put(ProfileOpenHelper.VOLUME, 0);
		cv.put(ProfileOpenHelper.VIBRATE, 0);
		return db.insert(ProfileOpenHelper.PROFILE_TABLE_NAME, null, cv);
	}
	
	void recordSelectedTime(int hourOfDay, int minute) {
		long now = System.currentTimeMillis();
		ContentValues cv = new ContentValues(1);
		cv.put(ProfileOpenHelper.LAST_USED, now);
		int rows = db.update(ProfileOpenHelper.HISTORY_TABLE_NAME, cv,
				String.format("%s = %d and %s = %d", ProfileOpenHelper.HOUR_OF_DAY, hourOfDay,
						ProfileOpenHelper.MINUTE, minute),
				null);
		if (rows == 0) { // haven't used this time before
			cv.put(ProfileOpenHelper.HOUR_OF_DAY, hourOfDay);
			cv.put(ProfileOpenHelper.MINUTE, minute);
			db.insert(ProfileOpenHelper.HISTORY_TABLE_NAME, null, cv);
			// now purge older times
			Cursor c = db.query(ProfileOpenHelper.HISTORY_TABLE_NAME,
		            new String[] { ProfileOpenHelper.LAST_USED },
					null, null, null, null, ProfileOpenHelper.LAST_USED + " desc",
					String.valueOf(ProfileOpenHelper.MAX_RECORDED_TIMES) + ",1");
			if (c.moveToFirst()) {
				long lastTime = c.getLong(0);
				String prune = String.format("delete from %s where %s <= %d",
						ProfileOpenHelper.HISTORY_TABLE_NAME, ProfileOpenHelper.LAST_USED,
						lastTime);
				db.execSQL(prune);
			}
		}
	}
	
}
